/*****************************************************************************

File:   otkLightingExample.java

Date          Build     Author        Version    Comments
01-Nov-12    P-20-16    dshah          $$1        Created
20-mar-15 P-30-05 gshmelev $$2  called GetCurrentSession

****************************************************************************/


package com.ptc.otkjavaexamples;

import com.ptc.cipjava.*;
import com.ptc.pfc.pfcSession.*;
import com.ptc.pfc.pfcCommand.*;
import com.ptc.pfc.pfcGlobal.*;
import com.ptc.pfc.pfcModel.*;
import com.ptc.pfc.pfcModelItem.*;
import com.ptc.pfc.pfcFeature.*;
import com.ptc.pfc.pfcSolid.*;
import javax.swing.JOptionPane;
import java.io.*;

import com.ptc.cipjava.*;
import com.ptc.pfc.pfcFamily.*;
import com.ptc.pfc.pfcServer.*;
import com.ptc.pfc.pfcWindow.*;
import com.ptc.wfc.wfcSolid.*;
import com.ptc.wfc.wfcDisplay.*;
import com.ptc.wfc.wfcSession.*;
import com.ptc.pfc.pfcSelect.*;
import com.ptc.pfc.pfcBase.*;


class otkLightingExample extends DefaultUICommandActionListener
{
    
    
    public otkLightingExample(LightType inLightType, boolean inRemoveLight,boolean inGetLightInformation )
    {
	mLightType = inLightType;
        mRemoveLight = inRemoveLight;
        mGetLightInformation = inGetLightInformation;
    }
    
    /**********************************************************************
	Overrides onCommand method from pfcUICommandActionListener depending upon 
	private members in the LightingExamples class 
	Executes any one of the following operation
	1.Add Light
	2.Remove Light
	3. Display Light Information

    **********************************************************************/
    public void OnCommand()
    {
	try
	    {	  
		
		WSession wSession = (WSession)(pfcSession.GetCurrentSession()); 
		
		WWindow window = (WWindow)(wSession.GetCurrentWindow());
		
		if(mRemoveLight == true)
		    RemoveLight(window);
		
		else if(mGetLightInformation == true)
		    DisplayLightInformation(window);
		
		else
		    AddLight(window,mLightType);	  
		
		return;
	    }
	catch (Exception e)
	    {
		System.out.println("1: " + e);
	    }
		return;
    }
    
    /**********************************************************************
	Adds a light source to the current window.
	Method takes all inputs required for a light source.
	Following type of lights are supported
	1.Point light (equivalent to lightbulb in Creo)
	2.Direction light (equivalent to distant in Creo)
	3.Spot light (equivalent to spot in Creo)

    **********************************************************************/

    public static void AddLight(WWindow windowObject,LightType type)
    {
	
	try
	    {
		WSession wSession = (WSession)(pfcSession.GetCurrentSession());
		
		LightSourceInstructions newLightInstrs = GetExistingLights(windowObject,true);
      
		/*
		  NOTE 1 : User can add maximum 5 lights in any window
		  SetLightInstructions() will throws pfcXToolkitUnsupported exception 
		  if number of lights are greater than 5
		*/
		
		if(newLightInstrs.getarraysize() >= 5)
		    {
			wSession.UIDisplayMessage("lights_example_msg.txt","USER Too many lights",null);
			return;
		    }
		
		/*
		  NOTE 2 : Method uses a point to determine source & aim location
		  of light source.
		*/
		
		
		wSession.UIDisplayMessage("lights_example_msg.txt","USER Select light position",null);
		SelectionOptions refSelopts = pfcSelect.SelectionOptions_Create("point");
		refSelopts.SetMaxNumSels(new Integer(1));
		
		Selections refSels = wSession.Select(refSelopts, null);
		
		Point3D position = refSels.get(0).GetPoint();   
		
		refSels.clear();
		
		wSession.UIDisplayMessage("lights_example_msg.txt","USER Select aim point",null);
		refSels = wSession.Select(refSelopts, null);
		
		Point3D directionPnt = refSels.get(0).GetPoint();	   
		
		wSession.UIDisplayMessage("lights_example_msg.txt","USER RGB Red value",null);      
		Double red = wSession.UIReadRealMessage(0.00,1.00);
		
		wSession.UIDisplayMessage("lights_example_msg.txt","USER RGB Green value",null);      
		Double green = wSession.UIReadRealMessage(0.00,1.00);
		
		wSession.UIDisplayMessage("lights_example_msg.txt","USER RGB Blue value",null);
		Double blue = wSession.UIReadRealMessage(0.00,1.00);
		
		wSession.UIDisplayMessage("lights_example_msg.txt","USER Light name",null);
		String lightName = wSession.UIReadStringMessage(Boolean.FALSE);
		
		ColorRGB color = pfcBase.ColorRGB_Create(red.doubleValue(),green.doubleValue(),blue.doubleValue());
		
		LightSourceInstruction spotLightinstr = 
		    wfcDisplay.LightSourceInstruction_Create(lightName,type,color,Boolean.TRUE);
		
		spotLightinstr.SetPosition(position);
		
		Vector3D direction = wfcSession.CreateVector3D(directionPnt.get(0),directionPnt.get(1),directionPnt.get(2));
		spotLightinstr.SetDirection(direction);
		
		/*
		  NOTE 3 : Spread angle is required only for spot light
		*/
		
		if(type == LightType.LIGHT_SPOT)
		    {
			
			wSession.UIDisplayMessage("lights_example_msg.txt","USER Spot Light Angle",null);
			Double spotAngle = wSession.UIReadRealMessage(0,180);
			
			spotLightinstr.SetSpreadAngle(spotAngle);	   
		    }	   
		
		newLightInstrs.append(spotLightinstr);
		
		windowObject.SetLightInstructions(newLightInstrs);
		
		/*
		  NOTE 4 : A window repaint or refresh is required to render an object after lights have been set
		*/
		
		windowObject.Refit();
		return;
		
	    }
	catch (Exception e)
	    {
		System.out.println("1: " + e);
	    }
	
	return;
    }
    
    /**********************************************************************
	Get all existing lights in a window.
	Method uses boolean SkipReadonlyLights to determine whether to collect readonly lights or not

    **********************************************************************/
    
    public static LightSourceInstructions GetExistingLights(WWindow windowObject,boolean SkipReadonlyLights)
    {
	try
	    {
		WSession wSession = (WSession)(pfcSession.GetCurrentSession());
		LightSourceInstructions lightInstrs = windowObject.GetLightInstructions();	
		
		LightSourceInstructions newLightInstrs = LightSourceInstructions.create();
		
		for(int ii=0;ii<lightInstrs.getarraysize();ii++)
		    {
			if(SkipReadonlyLights == true)
			    {
				if(lightInstrs.get(ii).GetType() == LightType.LIGHT_AMBIENT || lightInstrs.get(ii).GetType() == LightType.LIGHT_HDRI)
				    continue;
				
				if(lightInstrs.get(ii).GetType() == LightType.LIGHT_DIRECTION && lightInstrs.get(ii).GetName().compareTo("default distant_*") == 0 )
				    continue;
			    }
			
			newLightInstrs.append(lightInstrs.get(ii));
			
		    }
		return (newLightInstrs);
	    }
	catch (Exception e)
	    {
		System.out.println("1: " + e);
	    }
	return (null);
    }
    
    
    /**********************************************************************
	Removes a light from window.
	It asks user to enter name of the light to be removed.

    **********************************************************************/
    
    public static void RemoveLight(WWindow windowObject)
    {
	
	try
	    {
		WSession wSession = (WSession)(pfcSession.GetCurrentSession());
		wSession.UIDisplayMessage("lights_example_msg.txt","USER Light name",null);
		String lightName = wSession.UIReadStringMessage(Boolean.FALSE);
		
		
		/*
		  NOTE 5: Two default lights (distant1 and distant2) will always append some string
		  to its end.To remove the strings use xstring::Match with wildcard
		*/
		
		
		if((lightName.compareTo("distant1") == 0) || (lightName.compareTo("distant2") == 0 ))
		    lightName += ("_*");
		
		LightSourceInstructions lights = GetExistingLights(windowObject,true);
		
		for(int ii=0;ii<lights.getarraysize();ii++)
		    {
			if(lights.get(ii).GetName().compareTo(lightName) == 0 )
			    {
				lights.removerange(ii,ii+1);
				break;
			    }
		    }
		
		/*
		  NOTE 6: SetLightInstructions() will always remove all (non readonly)
		  lights & add lights passed to it. So remove desired light from a sequence 
		  and set that light sequence again into window
		*/
		
		windowObject.SetLightInstructions(lights);
		return;
		
	    }
	catch (Exception e)
	    {
		System.out.println("1: " + e);
	    }
	
	return;
    }
    
    /**********************************************************************
	Dump information of the light into a file.
	Displays the file using DisplayInformationWindow()
    **********************************************************************/
    
    public static void DisplayLightInformation(WWindow windowObject)
    {
	try
	    {
		WSession wSession = (WSession)(pfcSession.GetCurrentSession());
		FileWriter file = new FileWriter ("Lights.inf");
		BufferedWriter lightFile = new BufferedWriter (file);	
		
		LightSourceInstructions lights = GetExistingLights(windowObject,false);
		
		for(int ii=0;ii<lights.getarraysize();ii++)
		    {
			LightSourceInstruction light = lights.get(ii);
			
			lightFile.write("Name of the light " + light.GetName());
			lightFile.newLine();
			lightFile.write("Type of the light " + light.GetType().getValue());
			lightFile.newLine();
			
			
			lightFile.write("Position of source {" + light.GetPosition().get(0) + "," 
					+ light.GetPosition().get(1) + "," + light.GetPosition().get(2) + "}");
			lightFile.newLine();
			
			
			lightFile.write("Aim point {" + light.GetDirection().get(0) + ","
					+ light.GetDirection().get(1) + "," + light.GetDirection().get(2) + "}");
			lightFile.newLine();
			
			
			lightFile.write("RGB Color is {"  + light.GetColor().GetRed() + ","
					+ light.GetColor().GetGreen() + "," + light.GetColor().GetBlue() + "}");
			lightFile.newLine();
			
			
			if(light.GetType() == LightType.LIGHT_SPOT)
			    {
				lightFile.write("Spread Angle is " + light.GetSpreadAngle());
				lightFile.newLine();
			    }
			
			lightFile.newLine();
			
			
		    }
		
		Double XOffset = new Double(0);
		Double YOffset = new Double(0);
		Integer rows = new Integer(0);
		Integer columns = new Integer(0);
		
		lightFile.close();
		
		wSession.DisplayInformationWindow("./Lights.inf", XOffset, YOffset, rows, columns);
		
		return;
	    }
	catch (Exception e)
	    {
		System.out.println("1: " + e);
	    }
	return;
	
    }
    
    private LightType mLightType;
    private boolean mRemoveLight;
    private boolean mGetLightInformation;
    
    
};






